<template>
    <div class="container">
        <el-form class="form_box" ref="formRef" :model="form" :rules="rules" label-width="auto">
            <el-form-item label="任务标题" prop="title">
                <el-input class="title_inp" v-model="form.title" clearable :show-word-limit="true" maxlength="15" />
            </el-form-item>
            <el-form-item label="群发类型" prop="name" class="form-radio-item">
                <el-radio-group v-model="form.type" @change="handleChangeType">
                    <el-radio :label="1">客户群发</el-radio>
                    <el-radio :label="2">客户群群发</el-radio>
                </el-radio-group>
            </el-form-item>
            <el-form-item
                label="选择客户"
                :prop="form.custFilterEnable == 2 && form.type === 1
                    ? 'custFilterEnable'
                    : ''"
                class="form-radio-item"
                >
                <ZWSelectGroup v-if="form.type === 2" v-model="form" :option="modelOption" show-count="never">
                    <template #radioOption>
                        <el-radio :label="1">
                            全部群聊
                            <el-tooltip content="群聊中包含“我”的全部群聊。" placement="top">
                                <el-icon class="group-tootip-icon" color="#ccc" >
                                    <QuestionFilled />
                                </el-icon>
                            </el-tooltip>
                        </el-radio>
                        <el-radio :label="2">选择群聊</el-radio>
                        <el-radio :label="3">按客户标签选择群聊</el-radio>
                    </template>
                </ZWSelectGroup>
                <el-radio-group v-else v-model="form.custFilterEnable">
                    <el-radio :label="1">全部客户</el-radio>
                    <el-radio :label="2">筛选客户</el-radio>
                </el-radio-group>
            </el-form-item>
            <div v-if="showFilterLabelForm">
                <el-form-item v-if="form.type === 1" class="create-between-date" prop="createdBetween" >
                    <template #label>
                        <span>添加时间</span>
                        <el-tooltip content="成为企微好友时，最早的添加时间。" placement="top">
                            <el-icon class="group-tootip-icon" color="#ccc" >
                                <QuestionFilled />
                            </el-icon>
                        </el-tooltip>
                    </template>
                    <el-date-picker
                        v-model="form.createdBetween"
                        type="daterange"
                        range-separator="-"
                        start-placeholder="开始时间"
                        end-placeholder="结束时间"
                        :default-time="[
                            new Date(2000, 1, 1, 0, 0, 0),
                            new Date(2000, 1, 1, 23, 59, 59),
                        ]"
                        value-format="YYYY-MM-DD HH:mm:ss"
                    />
                </el-form-item>
                <el-form-item label="客户标签" prop="custFilter">
                    <ZWSelectLabelForm
                        v-model:type="form.custFilter.filterType"
                        v-model:tags="form.custFilter.tags"
                        @submitAfter="handleSubmitAfter('custFilter')"
                        @close="handleSubmitAfter('custFilter')"
                    />
                </el-form-item>
                <el-form-item label="排除客户标签" prop="custExcludeFilter">
                    <ZWSelectLabelForm
                        v-model:type="form.custExcludeFilter.filterType"
                        v-model:tags="form.custExcludeFilter.tags"
                        :exclude="tagsTypeExclude"
                        @submitAfter="handleSubmitAfter('custExcludeFilter')"
                        @close="handleSubmitAfter('custExcludeFilter')"
                    />
                </el-form-item>
            </div>
            <el-form-item label=" " class="estimated-number-form">
                <div>
                    (共选择<span class="estimated-number" >{{ estimatedNumber }}</span>个{{ form.type === 1 ? '客户' : '群聊' }})
                </div>
            </el-form-item>
            <el-form-item label="发送时间">
                <el-radio-group v-model="form.isSpecifySendTime" @change="form.specifySendTime = ''">
                    <el-radio :label="false">立即发送</el-radio>
                    <el-radio :label="true">定时发送</el-radio>
                </el-radio-group>
            </el-form-item>
            <div v-if="form.isSpecifySendTime">
                <el-form-item prop="SpecifySendTime" label=" ">
                    <el-date-picker v-model="form.specifySendTime" type="datetime" placeholder="请设置定时发送时间"
                        value-format="YYYY-MM-DD HH:mm:ss" />
                </el-form-item>
                <div class="desc">到达设定时候系统自动开始发送群消息</div>
            </div>
            <el-form-item label="发送内容">
                <div class="content">
                    <div class="content_btn">
                        <div>添加消息：</div>
                        <el-button @click="onAddMsg(1)">文本</el-button>
                        <el-button @click="onAddMsg(2)">图片</el-button>
                        <el-button @click="onAddMsg(3)">视频</el-button>
                        <el-button @click="onAddMsg(4)">文件</el-button>
                    </div>
                    <template v-for="(item, index) in form.content" :key="index">
                        <div v-if="item.type == 1" class="content_item">
                            <el-input v-model="item.content" type="textarea" placeholder="请输入消息内容" :rows="4" />
                            <el-icon class="content_del" @click="onDelMsg(index)">
                                <DeleteFilled />
                            </el-icon>
                        </div>
                        <div v-else class="content_item">
                            <div v-if="item.fileInfo" class="file_name">
                                <el-image
                                :src="item.fileInfo?.avatarUrl || item.fileInfo?.url" />
                                <span class="content_file_name" >{{ item.fileInfo?.name }}</span>
                                <el-icon @click="onDelMsg(index)">
                                    <CircleCloseFilled />
                                </el-icon>
                            </div>
                            <el-upload
                                :show-file-list="false"
                                :http-request="(val) => onSelectFile(val, index)"
                            >
                                <el-button :loading="item.uploadLoading">
                                    {{ item.fileInfo ? '重新选择' :`选择${btnName[item.type]}`  }}
                                </el-button>
                            </el-upload>
                            <el-icon v-if="!item.fileInfo" class="content_del" @click="onDelMsg(index)">
                                <DeleteFilled />
                            </el-icon>
                        </div>
                    </template>
                </div>
            </el-form-item>
            <el-form-item>
                <el-button @click="onRouteBack">取消</el-button>
                <el-button type="primary" @click="onSubmit(formRef)">确定</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script lang="ts" setup>
import { reactive, ref, onMounted, watchEffect, computed, watch, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { useRoute, useRouter } from "vue-router";

import ZWSelectLabelForm from "@renderer/components/win/ZWSelectLabel/ZWSelectLabelForm.vue";
import ZWSelectGroup from "@renderer/components/win/ZWSelectGroup/ZWSelectGroup.vue";
import { uploadFile2 } from "@renderer/ajax/api/common";
import {
    putUnlimitedSend,
    getUnlimitedSendDetail,
    getInfiniteSendEstimatedNumber
} from "@renderer/ajax/api/infiniteSend";

import { renderFileAvatar } from '../utils/index'
import { SELECT_LABEL_TYPE_MAP } from '@renderer/enums/common'

const router = useRouter();
const route = useRoute();
const formRef = ref<any>(null);

const modelOption = reactive({
    type: "custFilterEnable",
    selected: "custGroupList",
});

/**
 * 排除展示的标签
 */
const tagsTypeExclude = [
    SELECT_LABEL_TYPE_MAP['不包含以下任一标签'],
    SELECT_LABEL_TYPE_MAP['不包含以下所有标签'],
    SELECT_LABEL_TYPE_MAP['标签不为空'],
]
const form = reactive<any>({
    // 下面是新的接口所需要的字段-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    // ID 不为0 为编辑
    id: 0,
    // 标题
    title: "",
     // 1 客户群发 2 客户群群发
    type: 1,
     // 1 无过滤 2 标签过滤/客户群筛选 3 客户群标签过滤(只有 type 类型为客户群群发的时候生效)
    custFilterEnable: 1,
    // 好友添加时间 客户群发&过滤时间
    createdBetween: [],
    // 客户群发时生效 & custFilterEnable = 2, Group id
    custGroupList: [],
    // 客户标签
    custFilter: {
        // 0 不过滤标签、1 包含任意、 2 包含所有 3 不包含任意 4 不包含所有 5 标签为空 6 标签不为空
        filterType: undefined,
        // ids
        tags: [],
    },
    // 客户排除标签
    custExcludeFilter: {
        //  0 不过滤标签、1 包含任意、 2 包含所有 3 不包含任意 4 不包含所有 5 标签为空 6 标签不为空
        filterType: undefined,
        tags: [],
    },
    // true: 定时发送, false: 立即发送
    isSpecifySendTime: false,
    specifySendTime: null, // 允许为 null， 为 null时立即发送
    /**
     * @property {Number} id - 0代表新增
     * @property { 1 | 2 | 3 | 4 } type - 1 文本。 2 图片 3 视频 4 文件
     * @property {String} content - type 为1 文本时有用
     * @property {String} fileCode - 本地上传的文件code
     * @property {Object} fileInfo - 回显的信息: { code: "文件code", path: "文件路径", url: "web 请求URL", name: "文件名称", }
     */
    content: [
        {
            id: 0,
            type: 1, // 1 文本。 2 图片 3 视频 4 文件
            content: '', // type 为1 文本时有用
        },
    ],
});

/* ----------------------------校验筛选客户/筛选客户群-start---------------------------- */
/**
 * 校验客户标签
 */
 const checkCustFilter = (rule: any, value: any, callback: any) => {
    // 校验标签和标签的类型
    if(!form.custFilter.filterType) {
        return callback()
    }

    if ([5, 6].includes(form.custFilter.filterType)) {
        return callback()
    }

    if(!form.custFilter.tags?.length) {
        return callback( new Error('请选择客户标签'))
    }
    callback()
};

/**
 * 校验排除客户标签
 */
const checkCustExcludeFilter = (rule: any, value: any, callback: any) => {
    // 校验标签和标签的类型
    if(!form.custExcludeFilter.filterType) {
        return callback()
    }

    if ([5, 6].includes(form.custExcludeFilter.filterType)) {
        return callback()
    }

    if(!form.custExcludeFilter.tags?.length) {
        return callback( new Error('请选择排除客户标签'))
    }
    callback()
};

/**
 * 选择完标签后再去校验一遍
 * @param key 校验的key
 */
const handleSubmitAfter = (key) => {
    formRef.value.validateField([key])
}
/* ----------------------------校验筛选客户/筛选客户群-end---------------------------- */
const rules = reactive<any>({
    title: [{ required: true, message: "请输入任务标题", trigger: "blur" }],
    specifySendTime: [
        { required: true, message: "请设置定时发送时间", trigger: "blur" },
    ],
    custFilter: [{ validator: checkCustFilter }],
    custExcludeFilter: [{ validator: checkCustExcludeFilter }],
    custFilterEnable: [
        { required: true, message: "请选择客户类型", trigger: "blur" },
    ],
    custGroupList: [{ required: true, message: "请选择群聊", trigger: "blur" }],
});

/**
 * 改成promise形式的校验
 * @param keys 校验的keys
 */
 const validateField = (keys: Array<string>) => {
    return new Promise((resolve, reject) => {
        formRef.value?.validateField(keys, (result) => {
            if (result) {
                resolve(result)
            } else {
                reject(result)
            }
        })
    })
}

// 返回上一页
const onRouteBack = () => {
    router.back();
};


enum fileTypeName {
    "文本" = 1,
    "图片" = 2,
    "视频" = 3,
    "文件" = 4,
}

/**
 * 校验添加时间、客户标签、排除客户标签的函数
 */
 const validateFilterTags = (errCallback?) => {
    return new Promise((resolve, reject) => {
        // 未展示标签的情况下不做任何校验
        if (!showFilterLabelForm.value) {
            resolve(true);
            return
        }
        // 客户群群发校验，客户标签、排除客户标签必须填写一个
        // 5、6：标签为空/标签不为空
        const custFilterRules = [5, 6].includes(form.custFilter.filterType) || form.custFilter.tags?.length
        const custExcludeFilter = [5, 6].includes(form.custExcludeFilter.filterType) || form.custExcludeFilter.tags?.length
        const requiredKeys = [custFilterRules, custExcludeFilter]
        // 客户群发校验，添加时间、客户标签、排除客户标签必须填写一个
        if (form.type === 1) {
            requiredKeys.push(form.createdBetween?.length)
        }

        // 如果都没填写，则提示必填
        if(requiredKeys.every((result) => !result)) {
            if (!errCallback) {
                const requireErrorMsg = form.type === 1 ? '请筛选客户！' : '请选择客户标签！'
                ElMessage.warning(requireErrorMsg)
            } else {
                errCallback()
            }
            reject(false);
            return
        }

        resolve(true);
    })
}

/**
 * 校验发送内容，手动校验
 */
const validateContent = () => {
    return new Promise((resolve, reject) => {
        for (const contentItem of form.content) {
            if (contentItem.type === 1) {
                if (!contentItem.content) {
                    ElMessage.warning('请输入发送内容')
                    return reject(false);
                }
            } else {
                if (!contentItem.fileCode) {
                    ElMessage.warning(`请上传${fileTypeName[contentItem.type]}`)
                    return reject(false);
                }
            }
        }
        resolve(true)
    })
}

/**
 * 是否需要筛选标签的字段
 * 客户群发-筛选客户需要，客户群群发-按照客户标签选择群聊需要
 */
const isNeedFilterTags = computed(() => {
    return (form.type === 1 && form.custFilterEnable === 2) || (form.type === 2 && form.custFilterEnable === 3)
})

/**
 * 获取校验成功后筛选标签字段最终的结果
 * @param key 
 */
const getValidateFieldFilterTags = async (key: string) => {
    if (!isNeedFilterTags.value) {
        return {
            filterType: 0,
            tags: []
        }
    }

    try {
        await validateField([key])
        return {
            filterType: form[key]?.filterType || 0,
            tags: form[key]?.tags?.map?.(item => item.Id || item.id)
        }
    } catch (error) {
        return {
            filterType: 0,
            tags: []
        }
    }
}

// 提交表单
const onSubmit = async (formEl: any) => {
    await formEl.validate();
    await computedInfiniteSendEstimatedNumber();
    await validateContent()

    
    let params = {
        ...form,
        id: route.query.type === 'copy' ? 0 : form.id,
        // 好友添加时间 客户群发&过滤时生i奥
        createdBetween: form.type === 2 ? [] : form.createdBetween,
        // 客户群发时生效 & custFilterEnable = 2
        custGroupList: form.type === 2 && form.custFilterEnable === 2 ? form.custGroupList?.map(item => item.id) : [],
        // 客户标签
        custFilter: await getValidateFieldFilterTags('custFilter'),
        // 排除客户标签
        custExcludeFilter: await getValidateFieldFilterTags('custExcludeFilter'),
        content: form.content.map(item => {
            return {
                ...item,
                fileInfo: undefined
            }
        }),
        specifySendTime: form.isSpecifySendTime ? form.specifySendTime : null
    };

    // 校验预计客户数量
    if (!Number(estimatedNumber.value)) {
        ElMessageBox.alert(form.type === 1 ? '请选择需要群发的客户' : '请选择需要群发的客户群', '提示', {
            confirmButtonText: '好的',
        })
        return
    }
    // 校验是否存在已解散的
    if (form.custGroupList.some((item: any) => item.isDelete)) {
        await ElMessageBox.alert('系统已为您自动删除【已解散】的群聊！', '提示', {
            confirmButtonText: '好的',
        })
    }

    putUnlimitedSend(params).then((res: any) => {
        const message = form.id && route.query.type !== 'copy' ? "编辑任务成功" : "新建任务成功";
        ElMessage.success(message);
        onRouteBack();
    });
};
// 数据回显
const onLook = async () => {
    const res: any = await getUnlimitedSendDetail({ id: route.query.id });
    res.createdBetween = res.createdBetween || []
    const mergeCustTags = (tagFilterKey) => {
        res[tagFilterKey] = res[tagFilterKey] || {
            filterType: undefined,
            tags: [],
        }
        res[tagFilterKey].filterType = res[tagFilterKey]?.filterType || undefined
    }
    mergeCustTags('custExcludeFilter')
    mergeCustTags('custFilter')
    Object.assign(form, res)
    
    form.content.forEach(async item => {
        item.id = 0
        item.fileCode = item.fileInfo?.code
        if (item.type !== fileTypeName['文本']) {
            item.fileInfo.avatarUrl = renderFileAvatar(item.fileInfo.name, item.type)
        }
    })
};
onMounted(() => {
    route.query.id && onLook();
});

/* ----------------------------群发类型-start---------------------------- */
const handleChangeType = () => {
    // 重置客户标签与选择类型
    form.custFilterEnable = 1
    form.createdBetween = []
    form.custFilter = {
        filterType: undefined,
        tags: []
    }
    form.custExcludeFilter = {
        filterType: undefined,
        tags: []
    }
}
/* ----------------------------群发类型-end---------------------------- */

/** 是否展示追加的字段 */
const showFilterLabelForm = computed(() => {
    if (form.type === 1) {
        return form.custFilterEnable === 2
    }
    return form.custFilterEnable === 3
})

/* ---------------------------发送内容-start---------------------------- */
const fileRules = {
    // 文本
    1: '',
    // 图片
    2: '.JPG.PNG',
    // 视频
    3: '.MP4',
    // 文件
    4: '.PDF.XLS.XLSX.DOC.DOCX.PPT.PPTX.TXT.ZIP'
};

const btnName = ["", "文本", "图片", "视频", "文件"]
// 发送消息内容
const onAddMsg = (type: any) => {
    form.content.push({
        id: 0, // 0代表新增
        type: type, // 1 文本。 2 图片 3 视频 4 文件
        content: '', // type 为1 文本时有用
        fileCode: '',
    });
};

// 删除消息内容
const onDelMsg = (index: any) => {
    form.content.splice(index, 1);
    abortUpload?.abort()
};

/** 取消请求的对象 */
let abortUpload = null
// 选择文件上传
const onSelectFile = async ({ file }: any, index: any) => {
    const fileType = form.content[index].type;
    const fileName = file.name.split(".").at(-1).toUpperCase();
    // 校验格式
    if (!fileRules[fileType].includes(fileName)) {
        return ElMessage.error(`上传${btnName[fileType]}格式不正确`);
    }
    try {
        form.content[index].uploadLoading = true

        const res: any = await uploadFile2(file, (c) => {
            abortUpload = c
        });

        const avatarUrl = await renderFileAvatar(file.name, fileType)

        form.content[index] = {
            id: 0,
            type: fileType,
            content: '',
            fileCode: res.code,
            fileInfo: {
                ...res,
                avatarUrl
            }
        }
    } finally {
        form.content[index].uploadLoading = false
        abortUpload = null
    }

};
/* ---------------------------发送内容-end---------------------------- */

/* ----------------------------预计群发客户数量-start---------------------------- */
const estimatedNumber = ref(0)
const computedInfiniteSendEstimatedNumber = async (errCallback?) => {
    if (form.type === 1) {
        // 防止切换群发类型传参异常仍然调用接口
        if (![1, 2].includes(form.custFilterEnable)) {
            return
        }
    }

    const params = {
        // 1 客户群发 2 客户群群发
        type: form.type,
        // 1 无过滤 2 标签过滤/客户群筛选 3 客户群标签过滤(只有 type 类型为客户群群发的时候生效)  
        custFilterEnable: form.custFilterEnable,
        // 好友添加时间 客户群发&过滤时生i奥
        createdBetween: form.type === 1 && form.custFilterEnable === 2 ? form.createdBetween : [],
        // 客户群发时生效 & custFilterEnable = 2
        custGroupList: form.type === 2 ? form.custGroupList?.map(item => item.id) : [],
        // 客户标签
        custFilter: {
            filterType: form.custFilter?.filterType || 0,
            tags: form.custFilter?.tags?.map?.(item => item.Id || item.id)
        },
        // 排除客户标签
        custExcludeFilter:{
            filterType: form.custExcludeFilter?.filterType || 0,
            tags: form.custExcludeFilter?.tags?.map?.(item => item.Id || item.id)
        }
    }

    
    // 先校验一下通过在继续调用接口
    await validateFilterTags(errCallback)
    // 获取校验后结果的查询条件
    params.custFilter = await getValidateFieldFilterTags('custFilter')
    params.custExcludeFilter = await getValidateFieldFilterTags('custExcludeFilter')
    const res: any = await getInfiniteSendEstimatedNumber(params)
    estimatedNumber.value = res
}

watchEffect(() => {
    computedInfiniteSendEstimatedNumber(() => {
        // 未通过校验的情况下，重置为0
        estimatedNumber.value = 0
    })
})
/* ----------------------------预计群发客户数量-end---------------------------- */
</script>

<style scoped lang="scss">
.title_inp {
    width: 300px;
}

.desc {
    padding-left: 80px;
    margin-bottom: 18px;
    font-size: 12px;
    color: #999;
}

.zdy_btn {
    padding: 0;
}

.upload_desc {
    margin-top: 10px;
}

.container {
    min-width: 900px;
    padding: 16px;
    background: #fff;

    .form_box {
        width: 60%;
    }

    .num {
        color: #1432f5;
    }

    .clear {
        margin-left: 5px;
        cursor: pointer;

        &:hover {
            color: red;
        }
    }

    .item_margin {
        margin-bottom: 0;
    }

    .download {
        margin-left: 10px;
        color: #1432f5;
        cursor: pointer;
    }
}

.mobile_all {
    background: red;

    :deep(.el-textarea__inner) {
        border-radius: 0;
        cursor: default;

        &:hover {
            border: none;
        }
    }
}

.dialog_title {
    margin-bottom: 10px;
}

.content {
    .content_btn {
        display: flex;
    }

    .content_item {
        margin-top: 8px;
        display: flex;
        align-items: center;
        gap: 8px;

        .el-textarea {
            width: 320px;
        }

        .file_name {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 8px;

            width: 320px;
            height: 32px;
            line-height: 1;
            border-radius: 2px;
            background-color: #f5f5f5;

            .content_file_name {
                flex: 1;
                width: 0;
                margin: 0 8px;
                font-size: 12px;
                line-height: 1.5;
                color: #333;
                white-space: nowrap;
                text-overflow: ellipsis;
                overflow: hidden;
            }
            .el-image {
                width: 22px;
                height: 22px;
                :deep(.el-loading-spinner) {
                    top: 0;
                    margin-top: 0;
                    width: 100%;
                    height: 100%;
                    .circular {
                        width: 100%;
                        height: 100%;
                    }

                }
            }


            .el-icon {
                font-size: 16px;
                color: #cccccc;

                &:hover {
                    cursor: pointer;
                    color: var(--el-text-color-placeholder);
                }
            }
        }

        .content_del {
            cursor: pointer;
            vertical-align: middle;

            &:hover {
                color: red;
            }
        }
    }
}

.tag_list {
    margin-bottom: 10px;

    .tag {
        margin-right: 10px;
    }
}

.tag_btn {
    display: flex;
    align-items: center;
}

.create-between-date {
    :deep(.el-date-editor) {
        max-width: 320px;
    }
}

.group-tootip-icon {
    display: inline-block;
    height: 32px;
    line-height: 32px;
    vertical-align: middle;
    margin-left: 4px;
}


.estimated-number-form {
    margin: -12px 0 8px;
    font-size: 14px;
    color: #999;
    line-height: normal;
    .estimated-number {
        color: var(--el-color-primary);
    }
}

.form-radio-item {
    margin-bottom: 12px;
}
</style>
